{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "de6537c4",
   "metadata": {},
   "source": [
    "# BatchEvalRunner - Running Multiple Evaluations\n",
    "\n",
    "The `BatchEvalRunner` class can be used to run a series of evaluations asynchronously. The async jobs are limited to a defined size of `num_workers`.\n",
    "\n",
    "## Setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "db405f59",
   "metadata": {},
   "outputs": [],
   "source": [
    "%pip install llama-index-llms-openai llama-index-embeddings-openai"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4a8304f2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# attach to the same event-loop\n",
    "import nest_asyncio\n",
    "\n",
    "nest_asyncio.apply()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ff59a851",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import openai\n",
    "\n",
    "os.environ[\"OPENAI_API_KEY\"] = \"sk-...\"\n",
    "# openai.api_key = os.environ[\"OPENAI_API_KEY\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8d0b2364-4806-4656-81e7-3f6e4b910b5b",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Response\n",
    "from llama_index.llms.openai import OpenAI\n",
    "from llama_index.core.evaluation import (\n",
    "    FaithfulnessEvaluator,\n",
    "    RelevancyEvaluator,\n",
    "    CorrectnessEvaluator,\n",
    ")\n",
    "from llama_index.core.node_parser import SentenceSplitter\n",
    "import pandas as pd\n",
    "\n",
    "pd.set_option(\"display.max_colwidth\", 0)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "efe66f2a",
   "metadata": {},
   "source": [
    "Using GPT-4 here for evaluation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b9b98f89-d5b8-4d29-92f6-ad76d5060e9f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# gpt-4\n",
    "gpt4 = OpenAI(temperature=0, model=\"gpt-4\")\n",
    "\n",
    "faithfulness_gpt4 = FaithfulnessEvaluator(llm=gpt4)\n",
    "relevancy_gpt4 = RelevancyEvaluator(llm=gpt4)\n",
    "correctness_gpt4 = CorrectnessEvaluator(llm=gpt4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1298bbb4-c99e-431e-93ef-eb32c0a2fc2a",
   "metadata": {},
   "outputs": [],
   "source": [
    "documents = SimpleDirectoryReader(\"./test_wiki_data/\").load_data()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "41f0e53f-77a6-40d5-94ae-3f81b01af75c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# create vector index\n",
    "llm = OpenAI(temperature=0.3, model=\"gpt-3.5-turbo\")\n",
    "splitter = SentenceSplitter(chunk_size=512)\n",
    "vector_index = VectorStoreIndex.from_documents(\n",
    "    documents, transformations=[splitter]\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "400f486d",
   "metadata": {},
   "source": [
    "## Question Generation\n",
    "\n",
    "To run evaluations in batch, you can create the runner and then call the `.aevaluate_queries()` function on a list of queries.\n",
    "\n",
    "First, we can generate some questions and then run evaluation on them."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "976e0a93",
   "metadata": {},
   "outputs": [],
   "source": [
    "%pip install spacy datasets span-marker scikit-learn"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e31e10e6",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/yi/Code/llama/llama_index/llama-index-core/llama_index/core/evaluation/dataset_generation.py:212: DeprecationWarning: Call to deprecated class DatasetGenerator. (Deprecated in favor of `RagDatasetGenerator` which should be used instead.)\n",
      "  return cls(\n",
      "/Users/yi/Code/llama/llama_index/llama-index-core/llama_index/core/evaluation/dataset_generation.py:309: DeprecationWarning: Call to deprecated class QueryResponseDataset. (Deprecated in favor of `LabelledRagDataset` which should be used instead.)\n",
      "  return QueryResponseDataset(queries=queries, responses=responses_dict)\n"
     ]
    }
   ],
   "source": [
    "from llama_index.core.evaluation import DatasetGenerator\n",
    "\n",
    "dataset_generator = DatasetGenerator.from_documents(documents, llm=llm)\n",
    "\n",
    "qas = dataset_generator.generate_dataset_from_nodes(num=3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f3d6861e",
   "metadata": {},
   "source": [
    "## Running Batch Evaluation\n",
    "\n",
    "Now, we can run our batch evaluation!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "180a5d2e-9286-477b-9cd0-a5976d18d845",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.core.evaluation import BatchEvalRunner\n",
    "\n",
    "runner = BatchEvalRunner(\n",
    "    {\"faithfulness\": faithfulness_gpt4, \"relevancy\": relevancy_gpt4},\n",
    "    workers=8,\n",
    ")\n",
    "\n",
    "eval_results = await runner.aevaluate_queries(\n",
    "    vector_index.as_query_engine(llm=llm), queries=qas.questions\n",
    ")\n",
    "\n",
    "# If we had ground-truth answers, we could also include the correctness evaluator like below.\n",
    "# The correctness evaluator depends on additional kwargs, which are passed in as a dictionary.\n",
    "# Each question is mapped to a set of kwargs\n",
    "#\n",
    "\n",
    "# runner = BatchEvalRunner(\n",
    "#     {\"correctness\": correctness_gpt4},\n",
    "#     workers=8,\n",
    "# )\n",
    "\n",
    "# eval_results = await runner.aevaluate_queries(\n",
    "#     vector_index.as_query_engine(),\n",
    "#     queries=qas.queries,\n",
    "#     reference=[qr[1] for qr in qas.qr_pairs],\n",
    "# )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0eff6823",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n"
     ]
    }
   ],
   "source": [
    "print(len([qr for qr in qas.qr_pairs]))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b256b98c",
   "metadata": {},
   "source": [
    "## Inspecting Outputs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a4ab78d0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "dict_keys(['faithfulness', 'relevancy'])\n",
      "dict_keys(['query', 'contexts', 'response', 'passing', 'feedback', 'score', 'pairwise_source', 'invalid_result', 'invalid_reason'])\n",
      "True\n",
      "The population of New York City as of 2020 was 8,804,190.\n",
      "['=== Population density ===\\n\\nIn 2020, the city had an estimated population density of 29,302.37 inhabitants per square mile (11,313.71/km2), rendering it the nation\\'s most densely populated of all larger municipalities (those with more than 100,000 residents), with several small cities (of fewer than 100,000) in adjacent Hudson County, New Jersey having greater density, as per the 2010 census. Geographically co-extensive with New York County, the borough of Manhattan\\'s 2017 population density of 72,918 inhabitants per square mile (28,154/km2) makes it the highest of any county in the United States and higher than the density of any individual American city. The next three densest counties in the United States, placing second through fourth, are also New York boroughs: Brooklyn, the Bronx, and Queens respectively.\\n\\n\\n=== Race and ethnicity ===\\n\\nThe city\\'s population in 2020 was 30.9% White (non-Hispanic), 28.7% Hispanic or Latino, 20.2% Black or African American (non-Hispanic), 15.6% Asian, and 0.2% Native American (non-Hispanic). A total of 3.4% of the non-Hispanic population identified with more than one race. Throughout its history, New York has been a major port of entry for immigrants into the United States. More than 12 million European immigrants were received at Ellis Island between 1892 and 1924. The term \"melting pot\" was first coined to describe densely populated immigrant neighborhoods on the Lower East Side. By 1900, Germans constituted the largest immigrant group, followed by the Irish, Jews, and Italians. In 1940, Whites represented 92% of the city\\'s population.Approximately 37% of the city\\'s population is foreign born, and more than half of all children are born to mothers who are immigrants as of 2013. In New York, no single country or region of origin dominates.', \"New York, often called New York City or NYC, is the most populous city in the United States. With a 2020 population of 8,804,190 distributed over 300.46 square miles (778.2 km2), New York City is the most densely populated major city in the United States and more than twice as populous as Los Angeles, the nation's second-largest city. New York City is located at the southern tip of New York State. It constitutes the geographical and demographic center of both the Northeast megalopolis and the New York metropolitan area, the largest metropolitan area in the U.S. by both population and urban area. With over 20.1 million people in its metropolitan statistical area and 23.5 million in its combined statistical area as of 2020, New York is one of the world's most populous megacities, and over 58 million people live within 250 mi (400 km) of the city. New York City is a global cultural, financial, entertainment, and media center with a significant influence on commerce, health care and life sciences, research, technology, education, politics, tourism, dining, art, fashion, and sports. Home to the headquarters of the United Nations, New York is an important center for international diplomacy, and is sometimes described as the capital of the world.Situated on one of the world's largest natural harbors and extending into the Atlantic Ocean, New York City comprises five boroughs, each of which is coextensive with a respective county of the state of New York. The five boroughs, which were created in 1898 when local governments were consolidated into a single municipal entity, are: Brooklyn (in Kings County), Queens (in Queens County), Manhattan (in New York County), The Bronx (in Bronx County), and Staten Island (in Richmond County).As of 2021, the New York metropolitan area is the largest metropolitan economy in the world with a gross metropolitan product of over $2.4 trillion. If the New York metropolitan area were a sovereign state, it would have the eighth-largest economy in the world. New York City is an established safe haven for global investors.\"]\n"
     ]
    }
   ],
   "source": [
    "print(eval_results.keys())\n",
    "\n",
    "print(eval_results[\"faithfulness\"][0].dict().keys())\n",
    "\n",
    "print(eval_results[\"faithfulness\"][0].passing)\n",
    "print(eval_results[\"faithfulness\"][0].response)\n",
    "print(eval_results[\"faithfulness\"][0].contexts)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d8b20df9",
   "metadata": {},
   "source": [
    "## Reporting Total Scores"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "35fdbe0f",
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_eval_results(key, eval_results):\n",
    "    results = eval_results[key]\n",
    "    correct = 0\n",
    "    for result in results:\n",
    "        if result.passing:\n",
    "            correct += 1\n",
    "    score = correct / len(results)\n",
    "    print(f\"{key} Score: {score}\")\n",
    "    return score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2435e398",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "faithfulness Score: 1.0\n"
     ]
    }
   ],
   "source": [
    "score = get_eval_results(\"faithfulness\", eval_results)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5f57c938",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "relevancy Score: 1.0\n"
     ]
    }
   ],
   "source": [
    "score = get_eval_results(\"relevancy\", eval_results)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
